<template>
	<div
		:style="{
			width: projectDataInfo.screenWidth + 'px',
			height: projectDataInfo.screenHeight + 'px',
			backgroundColor: projectDataInfo.backgroundColor,
			backgroundImage: `url('${projectDataInfo.backgroundImage}')`,
			transform: `scale(${scalePercent / 100})  translate(0px, 0px)`,
		}"
		@click.self="onCanvasPanelClick"
		@contextmenu.prevent
		@dragover.prevent="onAllowDrop"
		@drop="onDrop"
		class="canvas-panel relative"
		data-id="canvasPanel"
		id="canvasPanel"
	>
		<ul :style="{ left: left + 'px', top: top + 'px' }" class="contextmenu" v-show="visible">
			<li @click="closeSelectedTag(selectedTag)">删 除</li>
			<li @click="copySelectedTag(selectedTag)">复 制</li>
			<li @click="moveSelectedTag(selectedTag, 9999)">置 顶</li>
			<li @click="moveSelectedTag(selectedTag, -9999)">置 底</li>
			<li @click="moveSelectedTag(selectedTag, 1)">上一层</li>
			<li @click="moveSelectedTag(selectedTag, -1)">下一层</li>
		</ul>
		<!--页面组件列表展示-->

		<vdr
			:active="item.uuid === activeElementUUID"
			:className="item.uuid === activeElementUUID ? 'actived' : 'noActived'"
			:data-uuid="item.uuid"
			:grid="[10, 10]"
			:h="getHeight(item)"
			:id="item.uuid"
			:key="item.uuid"
			:min-height="50"
			:min-width="50"
			:parent="true"
			:prevent-deactivation="true"
			:preventDeactivation="false"
			:ref="item.uuid"
			:scale-ratio="ratio"
			:style="getCommonStyle(item)"
			:w="getWidth(item)"
			:x="getChartX(item)"
			:y="getChartY(item)"
			@activated="onComponentActivated(item.uuid)"
			@contextmenu.prevent.native="openMenu(item, $event)"
			@dragging="onComponentDrag"
			@keyup.delete.native="onDelete"
			@keyup.native.alt.67="onCopyUUID"
			@keyup.native.ctrl.67="onCopy"
			@resizing="onComponentResize"
			class="engine-element-item"
			tabindex="99"
			v-for="item in activePage.elements"
		>
			<component
				:height="getHeight(item)"
				:is="item.elName"
				:ratio="ratio"
				:width="getWidth(item)"
				class="element-on-edit-pane"
				v-bind="{ ...item }"
				:ref="item.uuid"
				:parentnode="getthis()"
			/>
		</vdr>
		<div class="gridding" v-if="gridShow" :style="styleObject"></div>
	</div>
</template>

<script>
import { mapState, mapGetters } from 'vuex'
import domtoimage from 'dom-to-image'
import { _c_register_components_object } from '@client/plugins/index'
import { createUUID } from '@/common/js/mUtils'
// import OSS from 'ali-oss'
export default {
	data() {
		return {
			gridShow: true,
			visible: false,
			top: 0,
			left: 0,
			selectedTag: null,
			imgUrl: 'https://img.zczy56.com/',
			gridNum: 24,
		}
	},
	mounted() {
		this.$bus.$off('screenCapture')
		this.$bus.$off('gridShow')
		this.$bus.$on('screenCapture', () => {
			this.screenCapture()
		})
		this.$bus.$on('gridShowChange', val => {
			this.gridShow = val
		})
	},
	watch: {
		visible(value) {
			if (value) {
				document.body.addEventListener('click', this.closeMenu)
			} else {
				document.body.removeEventListener('click', this.closeMenu)
			}
		},
	},
	methods: {
		getthis() {
			return this
		},
		closeMenu() {
			this.visible = false
		},
		formatInt(num, prec = 1, ceil = true) {
			const len = String(num).length
			if (len <= prec) {
				return num
			}

			const mult = Math.pow(10, prec)
			return ceil ? Math.ceil(num / mult) * mult : Math.floor(num / mult) * mult
		},
		onAllowDrop() {},
		openMenu(item, e) {
			const menuMinWidth = 105
			const offsetLeft = this.$el.getBoundingClientRect().left // container margin left
			const offsetWidth = this.$el.offsetWidth // container width
			const maxLeft = offsetWidth - menuMinWidth // left boundary
			const left = e.clientX - offsetLeft // 15: margin right

			if (left > maxLeft) {
				this.left = maxLeft
			} else {
				this.left = left
			}
			this.top = e.clientY - this.$el.getBoundingClientRect().top
			if (this.scalePercent != 100) {
				this.left = (this.left * 100) / this.scalePercent
				this.top = (this.top * 100) / this.scalePercent
			}
			this.selectedTag = item
			this.visible = true
		},
		getChartX(item) {
			return item.props[0].fields[1].value[0].value.value
		},
		getChartY(item) {
			return item.props[0].fields[1].value[1].value.value
		},
		getWidth(item) {
			return item.props[0].fields[0].value[0].value.value
		},
		getHeight(item) {
			return item.props[0].fields[0].value[1].value.value
		},
		getCommonStyle(item) {
			//读取基本配置
			let chartWidth = item.props[0].fields[0].value[0].value.value
			let chartHeight = item.props[0].fields[0].value[1].value.value
			let chartX = item.props[0].fields[1].value[0].value.value
			let chartY = item.props[0].fields[1].value[1].value.value
			let zindex = item.props[0].fields[1].value[2].value.value
			let rotate = item.props[0].fields[2].value.value
			return {
				width: chartWidth + 'px',
				height: chartHeight + 'px',
				top: chartY + 'px',
				left: chartX + 'px',
				zIndex: zindex,
				transform: `rotate(${rotate}deg)`,
			}
		},
		screenCapture() {
			//
			//截图前把缩放比例设置为100
			// this.$store.dispatch('setScalePercent', 100)
			console.log(this.scalePercent)
			if (this.scalePercent != 100) {
				this.$bus.$emit('doneScreenCapture')
				this.$msgbox({
					title: '请先将缩放比例调整为100%',
				})
				return
			}
			const node = document.querySelector('#canvasPanel') //this.$refs.canvasPanel
			// 由于样式问题有白边，暂时无法解决，只能强制改css
			// node.style.left = 0
			// node.style.top = 0
			setTimeout(() => {
				domtoimage
					.toPng(node, {
						style: {
							transform: 'translate(-60px, -60px)',
						},
					})
					.then(dataUrl => {
						// node.style.left = '60px'
						// node.style.top = '60px'
						// let params = new FormData()
						const blob = this.$mUtils.dataURItoBlob(dataUrl)

						//
						const file = new window.File([blob], +new Date() + '.png', {
							type: 'image/png',
						})
						let OSS = require('ali-oss')
						const client = new OSS({
							// yourRegion填写Bucket所在地域。以华东1（杭州）为例，Region填写为oss-cn-hangzhou。
							// region: 'oss-cn-shanghai',
							// 从STS服务获取的临时访问密钥（AccessKey ID和AccessKey Secret）。
							accessKeyId: 'LTAI4FfzVCCkJgM3C4TvR1Wh',
							accessKeySecret: 'XVUJUA2YpHXDwCznqHQMlOtmCcHCwW',
							endpoint: 'oss-cn-shanghai.aliyuncs.com',

							// 填写Bucket名称。
							bucket: 'zczy',
						})

						// 填写Object完整路径。Object完整路径中不能包含Bucket名称。
						// 您可以通过自定义文件名（例如exampleobject.txt）或文件完整路径（例如exampledir/exampleobject.txt）的形式实现将数据上传到当前Bucket或Bucket中的指定目录。
						// data对象可以自定义为file对象、Blob数据或者OSS Buffer。
						client
							.multipartUpload('base-dir/' + file.name, file, {
								progress: async function (p) {
									console.log('Progress: ' + p)
								},
							})
							.then(result => {
								//
								let temp = this.projectDataInfo
								temp.thumbnailImage = this.imgUrl + result.name
								this.$store.dispatch('setProjectDataInfo', temp)
								this.$bus.$emit('doneScreenCapture')
							})
							.catch(err => {
								console.warn(err.message)
								this.$bus.$emit('doneScreenCapture')
							})
					})
					.catch(function (error) {
						console.error('截图出错了!', error)
						this.$bus.$emit('doneScreenCapture')
					})
			}, 500)
		},
		onDrop(e) {
			// console.log(e)
			//
			let left = e.offsetX - 60
			let top = e.offsetY - 60
			let title = e.dataTransfer.getData('title')
			this.$axios
				.post('/componentconfig/detail', { name: title })
				.then(res => {
					if (res.code === 200) {
						let dynamicConfig = res.body
						dynamicConfig.uuid = createUUID()
						dynamicConfig.props[0].fields[1].value[0].value.value = this.formatInt(left)
						dynamicConfig.props[0].fields[1].value[1].value.value = this.formatInt(top)
						this.$store.dispatch('addElement', dynamicConfig)
					}
				})
				.catch(e => {
					console.warn(e.message)
				})
		},
		onComponentActivated(uuid) {
			if (uuid) {
				this.$store.dispatch('setActiveElementUUID', uuid)
			} else {
				this.$store.dispatch('setActiveElementUUID', '')
			}
		},
		onComponentDrag(left, top) {
			if (this.activeElementIndex > -1) {
				let props = this.projectDataInfo.pages[0].elements[this.activeElementIndex].props[0]
				props.fields[1].value[0].value.value = this.formatInt(left)
				props.fields[1].value[1].value.value = this.formatInt(top)
				this.$store.dispatch('setProjectDataInfo', this.projectDataInfo)
			}
		},

		onComponentResize(left, top, width, height) {
			if (this.activeElementIndex > -1) {
				let props = this.projectDataInfo.pages[0].elements[this.activeElementIndex].props[0]
				props.fields[0].value[0].value.value = this.formatInt(width)
				props.fields[0].value[1].value.value = this.formatInt(height)
				props.fields[1].value[0].value.value = this.formatInt(left)
				props.fields[1].value[1].value.value = this.formatInt(top)
				this.$store.dispatch('setProjectDataInfo', this.projectDataInfo)
			}
		},

		onCanvasPanelClick(e) {
			e.target.dataset.id

			if (e.target.dataset.id === 'canvasPanel') {
				this.$store.dispatch('setActiveElementUUID', '')
			}
		},
		closeSelectedTag({ uuid }) {
			this.$confirm('确定删除?', '提示', {
				iconClass: 'el-icon-warning',
				callback: res => {
					if (res.action === 'confirm') {
						this.$store.dispatch('removeElement', uuid)
					}
				},
			})
		},
		copySelectedTag() {
			if (this.activeElement) {
				this.$store.dispatch('addElement', this.activeElement)
			}
		},
		moveSelectedTag({ uuid }, num) {
			this.$store.dispatch('moveSelectedTag', { uuid, num })
		},
		onDelete(e) {
			let uuid = e.currentTarget.dataset.uuid
			this.$confirm('确定删除?', '提示', {
				iconClass: 'el-icon-warning',
				callback: res => {
					if (res.action === 'confirm') {
						this.$store.dispatch('removeElement', uuid)
					}
				},
			})
		},
		onCopy() {
			if (this.activeElement) {
				this.$store.dispatch('addElement', this.activeElement)
			}
		},
		onCopyUUID(e) {
			let uuid = e.currentTarget.dataset.uuid
			window.alert(`请复制uuid: ${uuid}`)
		},
	},
	computed: {
		styleObject() {
			return {
				background: `linear-gradient(-90deg, rgba(255, 255, 255, 0.1) 1px, transparent 1px) 0% 0% / ${this.gridNum}px ${this.gridNum}px, linear-gradient(rgba(255, 255, 255, 0.1) 1px, transparent 1px) 0% 0% / ${this.gridNum}px ${this.gridNum}px`,
			}
		},
		ratio() {
			return this.scalePercent / 100
		},
		...mapState({
			scalePercent: state => state.scale.scalePercent,
			projectDataInfo: state => state.powereditor.projectDataInfo,
			activeElementUUID: state => state.powereditor.activeElementUUID,
			gridNum: state => state.powereditor.gridNum,
		}),
		...mapGetters(['activeElementIndex', 'activeElement', 'activePage']),
	},
	components: {
		..._c_register_components_object,
	},
}
</script>

<style lang="stylus" scoped>
.canvas-panel {
	transform-origin: 0 0;
	transition: 0.2s all ease-in-out;
	background-size: cover, contain;
	background-position: center, right bottom;
	background-repeat: no-repeat, no-repeat;
	box-shadow: rgba(0, 0, 0, 0.5) 0 0 30px 0;
	z-index: 90;
	.draggable.actived {
		border: 2px dotted #91cb74;
	}
}
.relative {
	position: relative;
	background-size: 100% 100%;
	top: 60px;
	left: 60px;
}
.gridding {
	// background: linear-gradient(-90deg, rgba(255, 255, 255, 0.1) 1px, transparent 1px) 0% 0% / 10px 10px, linear-gradient(rgba(255, 255, 255, 0.1) 1px, transparent 1px) 0% 0% / 10px 10px;
	position: absolute;
	top: 0;
	right: 0;
	left: 0;
	bottom: 0;
	z-index: 0;
	pointer-events: none;
	overflow: hidden;
}
.engine-element-item {
	position: absolute;
}
.contextmenu {
	margin: 0;
	background: #000000;
	z-index: 99999;
	position: absolute;
	list-style-type: none;
	padding: 5px 0;
	font-size: 14px;
	font-weight: 400;
	color: #999;
	cursor: pointer;
	// padding: 12px 18px;
	border-radius: 4px;
	li {
		margin: 0;
		padding: 10px 22px;
		cursor: pointer;
		display: block;
		&:hover {
			background: #282a36;
			color: #fff;
		}
	}
}
</style>
